package components.editor
{
	import MLP.mlp_layer3d;
	
	import SEApp.dialogs.se_alert;
	
	import UIFree.ObjectEvent;
	import UIFree.command.uif_commandManager;
	import UIFree.uif_component;
	
	import UIUtils.uif_util;
	
	import classes.c_events;
	import classes.c_imageTypes;
	import classes.c_uiEvents;
	
	import components.c_pcomponent;
	import components.c_toolBar;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.DisplayObject;
	import flash.display.PixelSnapping;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.utils.ByteArray;
	
	public class c_baseEditor extends c_pcomponent {
		private var _imageLayer		: c_imageLayer;
		private var _controlLayer	: c_pcomponent;
		private var _dragRect		: c_dragRect;
		private var _commandManager	: uif_commandManager;
		private var _menuToolBar	: c_toolBar;
		
		public function c_baseEditor(parent:uif_component) {
			super(parent);
		}
		
		
		override protected function createComponents():void {
			super.createComponents();
			var mm: Array 			= mainMenu;
			if (mm) _menuToolBar 	= new c_toolBar(cl.toolsBarLayer, mm);
			
			_commandManager = new uif_commandManager(workspace);
			_imageLayer 	= new c_imageLayer(this);//, 'white');
			_controlLayer 	= new c_pcomponent(this);
			_dragRect 		= new c_dragRect(_controlLayer);
			
			_imageLayer.blendMode = BlendMode.LAYER;
		}
		
		override public function dispose():void {
			if (_menuToolBar) _menuToolBar.dispose();
			_commandManager.dispose();
			super.dispose();
		}
		
		override protected function listenEvents():void {
			super.listenEvents();
			listenUIEvents();
			addEvent(c_events.GETRESULT, doGetResult, workspace);
		}
		
		protected function listenUIEvents(): void {
			addEvent(c_uiEvents.EXIT, doExit, workspace);
			addEvent(c_uiEvents.OPENFILE, doOpenFile, workspace);
			addEvent(c_uiEvents.SAVEAS, doSaveAs, workspace);
			addEvent(c_events.CHECKUIEVENT, doCheckEvent, workspace);
		}
		
		private function doCheckEvent(e: ObjectEvent): void {
			e.object.result = _menuToolBar.isMyUIEvent(e.object.type);
		}
		
		protected function doExit(e: Event): void {
			dispose();
		}
		
		protected function get mainMenu(): Array {
			return null;//ExternalInterface.call('getMainMenu', c_defaultMenu.list); 
		}
		
		override protected function getPortRect(a_parent: uif_component=null): Rectangle {
			return cl.workArea;
		}
		
		protected function fileFilters(): Array {
			return [new FileFilter('Все файлы', '*.*'), 
				new FileFilter('JPG формат', '*.' + c_imageTypes.JPG), 
				new FileFilter('PNG формат', '*.' + c_imageTypes.PNG), 
				new FileFilter('MLP формат', '*.' + c_imageTypes.MLP)];			
		}
		
		public function saveToFile(FileData: ByteArray, fileName: String='', fileExt: String=''): void {

			var alert: se_alert = new se_alert(cl.topLayer, cl.classes.locale.SAVEDESCR, null, true);
			alert.title.text = cl.classes.locale.WARNING;
			alert.okButton.addEvent(MouseEvent.CLICK, function(e: Event): void {				
				var fr: FileReference;
				fileName = fileName?fileName:genFileName('.' + (fileExt?fileExt:c_imageTypes.JPG));
				fr = new FileReference();
				fr.save(FileData, fileName);
			});
			alert.show();
		}
		
		
		public function openFile(): void {
			openFileDialog(function(a_data: ByteArray, fileType: String): void {
				c_imageTypes.loadBytes(workspace, a_data, fileType);
			});
		}
		
		protected function openFileDialog(afterLoadFile: Function): void {
			var _fref: FileReference = new FileReference();
			
			function removeFREvents(): void {
				_fref.removeEventListener(Event.COMPLETE, doCompleteHandler);
				_fref.removeEventListener(Event.SELECT, doSelectHandler);
			}
			
			function doSelectHandler(e: Event): void {
				_fref.load();
			}
			
			function doCompleteHandler(e: Event): void {
				afterLoadFile(_fref.data, _fref.type);
				removeFREvents();
			}
			
			_fref.addEventListener(Event.COMPLETE, doCompleteHandler);
			_fref.addEventListener(Event.SELECT, doSelectHandler);
			
			_fref.browse(fileFilters());
		}
		
		protected function genFileName(ext: String): String {
			return genName() + ext;
		}
		
		public function get dragRect(): c_dragRect {
			return _dragRect;
		}
		
		public function get imageLayer(): c_pcomponent {
			return _imageLayer;
		}
		
		public function get controlLayer(): c_pcomponent {
			return _controlLayer;
		}
		
		
		public function hitElement(): c_baseElement {
			var hitElement: c_baseElement = null;
			imageLayer.forEach(function(elem: c_baseElement): void {
				if (elem.visible && elem.hitMouse) hitElement = elem;
			}, c_baseElement);
			return hitElement;
		}
		
		public function getNewElementMaxRect(): Rectangle {
			return _imageLayer.getInner(10, 10, -10, -10);
		}
		
		protected function doSaveAs(e: Event): void {
			var obj: Object = {
				result: null
				//,resize: new Point(300, 300)
			}
			workspace.dispatchEvent(new ObjectEvent(c_events.GETRESULT, obj));
			if (obj.result) saveToFile(obj.result, '', obj.type);
			else cl.alert(locale.WARNING, locale.EMPTYRESULT);
		}
		
		protected function doOpenFile(e: Event): void {
			openFile();
		}
		
		public function getResultElement(resize: Point=null): Object {
			var elems: Array = getVisibleElems();
			if (elems.length > 0) {
				if (elems.length == 1) {
					var child: c_baseElement = elems[0];
					if (child is c_multiLayerElement) {
						var layer: mlp_layer3d = (child as c_multiLayerElement).layer3D;
						if (resize) layer = layer.resize(resize);
						return layer;
					}
				}
			}
			return paintFromBitmap(false, resize);
		}
		
		protected function doGetResult(e: ObjectEvent): void {
			if (getVisibleElems().length) {
				var element: Object = getResultElement(e.object.resize);
				if (element is mlp_layer3d) {
					var mlp: mlp_layer3d = element as mlp_layer3d;
					/*
					var rect: Rectangle = (element as mlp_layer3d).layersRect;
					cl.editorLayer.addChild(element as DisplayObject);
					element.x = (cl.editorLayer.width - rect.width) / 2;
					element.y = (cl.editorLayer.height - rect.height) / 2;
					
					var preview: BitmapData = (element as mlp_layer3d).getPreview(e.object.previewSize);
					app.addChild(new Bitmap(preview));
					*/
					
					e.object.type 	= c_imageTypes.MLP;
					e.object.result = c_imageTypes.encodeFromMLP(mlp);
					var nElem: Boolean = !mlp.parent;
					if (nElem) {
						element.visible = false;
						addChild(element as mlp_layer3d);
					}
					if (e.object.previewSize) {
						var preview: BitmapData = (element as mlp_layer3d).getPreview(e.object.previewSize);
//						var preview: BitmapData = (element as mlp_layer3d).getPreview(e.object.previewSize);
//						app.addChild(new Bitmap(preview));
						e.object.preview = c_imageTypes.encodeFromJPG(preview, cl.getExifHeader());
						preview.dispose();
					}
					if (nElem) mlp.dispose();
				} else {
					var bmd: BitmapData = element as BitmapData;
					if (bmd) {
						e.object.type 	= c_imageTypes.JPG;
						e.object.result = c_imageTypes.encodeFromJPG(bmd, cl.getExifHeader());
					}
				}
			} else e.object.result = null;
		}
		
		public function getVisibleElems(a_class: Class=null): Array {
			if (a_class == null) a_class = c_baseElement;
			var result: Array = new Array();
			_imageLayer.forEach(function(elem: DisplayObject): void {
				if (elem.visible) result.push(elem);
			}, a_class);	
			return result;
		}
		
		protected function getBitmaps(optimize: Boolean=false): Array {
			var result	: Array = new Array();
			var offset	: Point = new Point(Number.MAX_VALUE, Number.MAX_VALUE);
			var elems	: Array = getVisibleElems();
			
			elems.forEach(function(elem: c_baseElement, i: int, arr: Array): void {
				if (offset.x > elem.x) offset.x = elem.x;
				if (offset.y > elem.y) offset.y = elem.y;
			});
			
			elems.forEach(function(elem: c_baseElement, i: int, arr: Array): void {
				var bmp		: DisplayObject = elem.exportFromMLP(optimize);
				bmp.x -= offset.x;
				bmp.y -= offset.y;
				
				result.push(bmp);
			});
			return result;
		}
		
		
		public function allRect(): Rectangle {
			var result: Rectangle;
/*			_imageLayer.forEach(function(item: c_baseElement): void {
				if (!item.mask && item.visible) {
					if (!result)
						result = item.getBounds(_imageLayer);
					else result = result.union(item.getBounds(_imageLayer));
				}
			}, c_baseElement);*/
			
			var bmd: BitmapData = new BitmapData(_imageLayer.width, _imageLayer.height, true, 0);
			bmd.draw(_imageLayer);
			result = bmd.getColorBoundsRect(0xFF000000, 0, false);
			bmd.dispose();
			return result;
		}
		
		public function paintFromBitmap(transparent: Boolean=false, resize: Point=null): BitmapData {
			var rect	: Rectangle = allRect();
			var bmd		: BitmapData;
			if (rect) {
				var mat: Matrix = new Matrix();
				if (resize && !resize.equals(rect.size)) {
					var center: Point = new Point(rect.width / 2, rect.height / 2);
					bmd = new BitmapData(resize.x, resize.y, transparent, transparent?0:0xFFFFFF);
					var scale	: Number 	= resize.x/rect.width;
					mat.translate(-rect.x - center.x, -rect.y - center.y);
					mat.scale(scale, scale);
					mat.translate(resize.x / 2, resize.y / 2);
					bmd.draw(_imageLayer, mat);
				} else {
					bmd = new BitmapData(rect.width, rect.height, transparent, transparent?0:0xFFFFFF);
					mat.translate(-rect.x, -rect.y);				
					bmd.draw(_imageLayer, mat);
				}
			} 
			return bmd;
		}
		
		protected function get currentImage(): c_baseElement {
			return _dragRect.link;
		}
		
		
		public function checkAndSelectObject(obj: DisplayObject): void {
			if (imageLayer.contains(obj)) {
				if (obj is c_baseElement) {
					var be: c_baseElement = obj as c_baseElement;
					be.executeMySelect();
				} else {
					if (obj.parent) checkAndSelectObject(obj.parent);
					else dragRect.executeUnLink();
				}
			} else if (obj is Stage) dragRect.executeUnLink();
			//			else if (_dragRect.coordinates(obj))
		}
	}
}